# -*- encoding: utf-8 -*-
import datetime
from typing import List, Optional

from bct.tools.common.bct4.base_dto import JsonDTO
from bct.tools.common.datetime_util import trans_datetime, is_weekend


class Holiday(JsonDTO):
    holiday: Optional[str]
    note: Optional[str]

    def __init__(self, param: Optional[dict] = None):
        if param:
            self.holiday = param.get('holiday', '')
            self.note = param.get('note', '')
        else:
            self.holiday = None
            self.note = None

    def to_dict(self):
        return {
            'holiday': self.holiday,
            'note': self.note
        }


class TradingCalendarDTO(JsonDTO):
    id: Optional[str]
    calendar_id: Optional[str]
    calendar_name: Optional[str]
    holidays: List[Holiday]
    holidays_dt: Optional[List[datetime.datetime]] = None
    version: int

    def __init__(self, param: Optional[dict] = None):
        if param:
            self.id = param.get('id', None)
            self.calendar_id = param.get('calendarId', '')
            self.calendar_name = param.get('calendarName', '')
            self.version = param.get('version', 1)
            holidays = []
            for holiday in param.get('holidays', []):
                h = Holiday(holiday)
                holidays.append(h)
            self.holidays = holidays
        else:
            self.id = None
            self.calendar_id = None
            self.calendar_name = None
            self.version = 1
            self.holidays = []

    def is_in_holiday(self, date_time: datetime) -> bool:
        """
        是否在假日(包括周末)
        :param date_time:
        :return:
        """
        if self.holidays_dt is None:
            self.holidays_dt = []
            for h in self.holidays:
                hd = trans_datetime(h.holiday)
                self.holidays_dt.append(hd)
        for h in self.holidays_dt:
            if h.date() == date_time.date():
                return True
        if is_weekend(date_time):
            return True
        return False

    def next_work_day(self, date_time: datetime, day_offset=0) -> datetime:
        """
        移动到下一个工作日
        :param date_time:
        :param day_offset: 默认是0，1表示是下一个工作日
        :return:
        """
        day = date_time
        # move start
        while self.is_in_holiday(day):
            day = day + datetime.timedelta(days=1)
        # plus days
        i = 0
        while i < day_offset:
            day = self.next_work_day(day + datetime.timedelta(days=1))
            i += 1
        return day

    def to_dict(self):
        holidays = []
        for h in self.holidays:
            holidays.append(h.to_dict())
        return {
            'id': self.id,
            'calendarId': self.calendar_id,
            'calendarName': self.calendar_name,
            'holidays': holidays,
            'version': self.version
        }
